/*
 * file:  program.h (contains declarations of Program, StmtList, Stmt, Expr)
 * Author: Jeremy Johnson 
 * Date: 1/31/06
 *
 * Description:
 */
#include <iostream>
#include <string>
#include <map>
#include <list>

using namespace std;



class Expr
{
public:
	Expr() {};
	virtual ~Expr() {};  
	virtual int eval(map<string,int> T) const = 0;  

private:
};

class Number : public Expr
{
public:
	Number(int value = 0);
	virtual int eval(map<string,int> T) const;
private:
	int value_;
};

class Ident : public Expr
{
public:
	Ident(string name = "");
	virtual int eval(map<string,int> T) const;
private:
	string name_;
};

class Times : public Expr
{
public:
	Times(Expr * op1 = NULL, Expr * op2 = NULL);
	virtual ~Times() {delete op1_; delete op2_;};
	virtual int eval(map<string,int> T) const;
private:
	Expr* op1_;
	Expr* op2_;
};

class Plus : public Expr
{
public:
	Plus(Expr* op1 = NULL, Expr* op2 = NULL);
	virtual ~Plus() {delete op1_; delete op2_;};
	virtual int eval(map<string,int> T) const;
private:
	Expr* op1_;
	Expr* op2_;
};

class Minus : public Expr
{
public:
	Minus(Expr* op1 = NULL, Expr* op2 = NULL);
	virtual ~Minus() {delete op1_; delete op2_;};
	virtual int eval(map<string,int> T) const;
private:
	Expr* op1_;
	Expr* op2_;
};

class StmtList;

class Stmt 
{
public:
	Stmt() {};
	virtual ~Stmt() {};  
	virtual void eval(map<string,int> &T) const = 0;  

private:
};


class AssignStmt: public Stmt
{
public:
	AssignStmt(string name="", Expr *E=NULL);
	~AssignStmt() {delete E_;}; 
	void eval(map<string,int> &T) const;
private:
	string name_;
	Expr* E_;
};

class IfStmt: public Stmt
{
public:
	IfStmt(Expr *E,StmtList *S1, StmtList *S2);
//~IfStmt() {delete E_; delete S1_; delete S2_;};
	~IfStmt() {delete E_;};
	void eval(map<string,int> &T) const;
private:
	Expr* E_;
	StmtList *S1_;
	StmtList *S2_;
};

class WhileStmt: public Stmt
{
public:
	WhileStmt(Expr *E,StmtList *S);
//~WhileStmt() {delete E_; delete S_;};
	void eval(map<string,int> &T) const;
private:
	Expr* E_;
	StmtList *S_;
};


class StmtList 
{
public:
	StmtList() {};
	void eval(map<string,int> &T);  
	void insert(Stmt *T);  

private:
	list<Stmt*> SL_;
};

class Program 
{
public:
	Program(StmtList *SL);
	~Program() {delete SL_; };  
	void dump();
	void eval();  

private:
	StmtList *SL_;
	map<string,int> SymbolTable_;
};
